package com.ebspp.client.serverManager;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;

import com.ebspp.global.General;
import com.ebspp.thrift.DataMsg;
import com.ebspp.thrift.DataWrite;
import com.ebspp.thrift.Identity;
import com.ebspp.thrift.ResourceType;

/**
 * Write connection, responsible for write to the servers
 * If it can provision resources, the resource is positive
 * other wise it will be turned to negative
 * 
 * @author x23pan
 *
 */
public class WriteConnection {
	private int wPort;
	private String server;
	private Identity id;
	private ResourceType resType;
	
	private DataWrite.Client wClient;
	TTransport transport;
	
	private IStat stat;
	int resource = 0;
	
	Object mutex = new Object();
	
	public WriteConnection(String server, int wPort, ResourceType resType, Identity id, IStat stat)
	{
		this.server = server;
		this.wPort = wPort;
		this.resType = resType;
		this.id = id;
		
		this.stat = stat;
	}
	
	public void connect() throws TTransportException
	{
		transport = new TSocket(server, wPort);
		//TTransport wTransport = new TFramedTransport(socket);
		TProtocol protocol = new TBinaryProtocol(transport);
		wClient = new DataWrite.Client(protocol);
		transport.open();
	}
	
	public void close()
	{
		transport.close();
	}
	
	//write to the server
	public List<DataMsg> write(List<DataMsg> data) throws TException
	{
		synchronized(mutex)
		{
			return wClient.writeEBSPP(data, resType, id);
		}
	}
	//provision resources
	public boolean provision(int amount) throws TException
	{
		Map<ResourceType, Integer> askRes = new HashMap<ResourceType, Integer>();
		askRes.put(resType, amount);
		boolean result;
		synchronized(mutex)
		{
			result = wClient.provision(askRes, id);
		}
		//note that amount can be negative, for release
		if(result)
			resource = Math.abs(resource) + amount;
		else
			resource = 0 - Math.abs(resource);
		
		return result;
	}

	
	public String getServer()
	{
		return server;
	}
	public ResourceType getResType()
	{
		return resType;
	}
	public int getResource()
	{
		return resource;
	}
	
	public boolean equals(Object obj)
	{
		if(obj == null)
			return false;
		if(obj instanceof WriteConnection)
		{
			WriteConnection conn = (WriteConnection)obj;
			if(id.equals(conn.id) && server.equals(conn.server) && resType.equals(conn.resType))
				return true;
		}
		return false;
	}
	
	public int hashCode()
	{
		return id.hashCode() * 3 + server.hashCode() * 13 + resType.hashCode() * 17;
	}
}
